using System;
using System.Collections.Generic;
using System.Text;
using FlatRedBall;
using FlatRedBall.Input;
using FlatRedBall.AI.Pathfinding;
using FlatRedBall.Graphics.Animation;
using FlatRedBall.Graphics.Particle;

using FlatRedBall.Math.Geometry;
using FlatRedBall.Math.Splines;
using BitmapFont = FlatRedBall.Graphics.BitmapFont;
using Cursor = FlatRedBall.Gui.Cursor;
using GuiManager = FlatRedBall.Gui.GuiManager;

#if FRB_XNA || SILVERLIGHT
using Keys = Microsoft.Xna.Framework.Input.Keys;
using Vector3 = Microsoft.Xna.Framework.Vector3;
using Texture2D = Microsoft.Xna.Framework.Graphics.Texture2D;


#endif
using NereusGame.Entities.Projectiles;
using NereusGame.Entities.Ships;

namespace NereusGame.Entities.Weapons
{
	public partial class Weapon
	{
        private const int MAX_LEVEL = 5;                                // Maximum Level of any weapon
        protected const string CONTEN_MANAGER = "NereusGameContent";   // Name of the contentManager
        protected float damage;
        protected float defaultVelocity;
        protected Vector3 shootingPosition;
        public string Name;
        protected enum WeaponState
        {
            ReadyToShoot,
            DownTime,
        }

        protected WeaponState state;                                    // tracks the state a weapon
        public Queue<Projectile> aliveAmmo;                          // has all the alive projectiles
        public Queue<Projectile> deadAmmo;                           // has all the dead projectiles
        protected int fireRate;                                         // track the fireRate of the weapon
        protected int initialFireRate;                                  // Initial firing rate
        protected int Level;                                               // tracks current level of weapon
        protected Ship Shooter;
        protected Random rand;

		private void CustomInitialize()
		{
            InitializeWeapon();

            rand = new Random();

		}

		private void CustomActivity()
		{
            ProjectileActivity();
            CheckLevel();
            CheckFireRate();

		}

		private void CustomDestroy()
		{
            if (aliveAmmo != null)
            {
                for (int i = 0; i < aliveAmmo.Count; i++)
                {
                    if(aliveAmmo.Peek() != null)
                        aliveAmmo.Dequeue().Destroy();
                }
            }

            if (deadAmmo != null)
            {
                for (int i = 0; i < deadAmmo.Count; i++)
                {
                    if (deadAmmo.Peek() != null)
                        deadAmmo.Dequeue().Destroy();
                }
            }
            

		}

        private static void CustomLoadStaticContent(string contentManagerName)
        {


        }

        // Initialize the weapon
        private void InitializeWeapon()
        {
            Name = "N/A";
            initialFireRate = 50;
            Level = 0;
            ReadyToShootState();
            aliveAmmo = new Queue<Projectile>();
            deadAmmo= new Queue<Projectile>();
            damage = 0;
            shootingPosition = Vector3.Zero;
            defaultVelocity = 0;

        }


        // allows the projectile to peroform its activities and also moves a dead projectile from aliveAmmo to deadAmmo.
        private void ProjectileActivity()
        {
            
            for (int i = 0; i < aliveAmmo.Count; i++)
            {
                aliveAmmo.Peek().Activity();
                if (!aliveAmmo.Peek().IsAlive())
                {
                    deadAmmo.Enqueue(aliveAmmo.Dequeue());
                    continue;
                }
                aliveAmmo.Enqueue(aliveAmmo.Dequeue());
            }
             
        }

        // deselect weapon when level of weapon is below 1
        private void CheckLevel()
        {
            if (Level < 1)
                state = WeaponState.DownTime;
        }

        // when weapon is in its downTime state it will decrement the fireRate counter.
        private void CheckFireRate()
        {
            if (state == WeaponState.DownTime)
            {
                fireRate--;
                if (fireRate <= 0)
                    ReadyToShootState();
            }
        }

        // This will reset the fireRate and allows the weapon to shoot the next projectile
        private void ReadyToShootState()
        {
            state = WeaponState.ReadyToShoot;
            fireRate = initialFireRate;
        }


        // this function selects which shoot function to use depending on weapon level
        public bool Shoot(Ship s, Vector3 pos, float offset, float rotation, Vector3 velocity)
        {
            if (state == WeaponState.ReadyToShoot)
            {
                Shooter = s;
                if (Level == 1)
                {
                    Shoot1(pos, offset, rotation, velocity);
                }
                else if (Level == 2)
                {
                    Shoot2(pos, offset, rotation, velocity);
                }
                else if (Level == 3)
                {
                    Shoot3(pos, offset, rotation, velocity);
                }
                else if (Level == 4)
                {
                    Shoot4(pos, offset, rotation, velocity);
                }
                else if (Level == 5)
                {
                    Shoot5(pos, offset, rotation, velocity);
                }
                return true;
            }
            return false;
        }

        public virtual void Shoot1(Vector3 pos, float offset, float rotation, Vector3 velocity)
        {
            if (state == WeaponState.ReadyToShoot)
            {
                // calculate direciton
                shootingPosition.X = (float)Math.Cos(rotation + (float)Math.PI / 2f) + pos.X;
                shootingPosition.Y = (float)Math.Sin(rotation + (float)Math.PI / 2f) + pos.Y;
                Vector3 direction = (shootingPosition - pos);
                direction.Normalize();

                // calculate shootingposition
                shootingPosition = pos + direction * offset;

                deadAmmo.Peek().Position = shootingPosition;  // this will set the position of the projectile
                deadAmmo.Peek().Shoot(Shooter, direction, rotation, velocity);
                aliveAmmo.Enqueue(deadAmmo.Dequeue());  // send it to the aliveAmmo queue.
                state = WeaponState.DownTime;
            }
        }

        public virtual void Shoot2(Vector3 pos, float offset, float rotation, Vector3 velocity)
        {
            Shoot1(pos, offset, rotation, velocity);
        }

        public virtual void Shoot3(Vector3 pos, float offset, float rotation, Vector3 velocity)
        {
            Shoot1(pos, offset, rotation, velocity);
        }

        public virtual void Shoot4(Vector3 pos, float offset, float rotation, Vector3 velocity)
        {
            Shoot1(pos, offset, rotation, velocity);
        }

        public virtual void Shoot5(Vector3 pos, float offset, float rotation, Vector3 velocity)
        {
            Shoot1(pos, offset, rotation, velocity);
        }



        // This function will increment the weapon's level by 1.
        public bool UpgradeWeapon()
        {
            // jsut to prevent from crashing.
            if (aliveAmmo == null || deadAmmo == null)
                return false;

            if (Level < MAX_LEVEL)
            {
                Level++;
                UpdateUpgrade();
                for (int i = 0; i < aliveAmmo.Count; i++)
                {
                    aliveAmmo.Peek().Damage = damage;
                    aliveAmmo.Peek().DefaultVelocity = defaultVelocity;
                    aliveAmmo.Enqueue(aliveAmmo.Dequeue());
                }

                for (int i = 0; i < deadAmmo.Count; i++)
                {
                    deadAmmo.Peek().Damage = damage;
                    deadAmmo.Peek().DefaultVelocity = defaultVelocity;
                    deadAmmo.Enqueue(deadAmmo.Dequeue());
                }                
                return true;
            }
            return false;
        }

        // upgrades the weapon accordign to level
        private void UpdateUpgrade()
        {
            if (Level == 1)
                Upgrade1();
            else if (Level == 2)
                Upgrade2();
            else if (Level == 3)
                Upgrade3();
            else if (Level == 4)
                Upgrade4();
            else if (Level == 5)
                Upgrade5();

        }

        public virtual void playWeaponSound()
        {

        }


        // This is so bad :(
        protected virtual void Upgrade1()
        {

        }

        protected virtual void Upgrade2()
        {

        }

        protected virtual void Upgrade3()
        {

        }

        protected virtual void Upgrade4()
        {

        }

        protected virtual void Upgrade5()
        {

        }

        public void SetFireRate(int rate)
        {
             initialFireRate = rate;
        }
	}
}
